package systems.spidron 
{
	import flash.display.Graphics;
	import flash.geom.Point;
	import shapes.shapes2D.distribution.goldenRatio.GoldenRatio;
	import utils.GeomUtils;
	/**
	 * @author Nicolas Barradeau
	 * http://en.nicoptere.net
	 * 
	 * based on the description here
	 * http://edan.szinhaz.org/SpidroNew/general_concept.htm
	 * 
	 */
	public class Spidron
	{
		
		private var settings:Object;
		
		private var _x:Number;
		private var _y:Number;
		private var _length:Number;
		private var _angle:Number;
		private var _offsetAngle:Number;
		
		private var halfPi:Number = Math.PI * .5;
		private var _points:Vector.<Point> = new Vector.<Point>();
		
		public function Spidron( x:Number = 0, y:Number = 0, length:Number = 100, angle:Number = 0, offsetAngle:Number = NaN ) 
		{
			
			this._x = x;
			this._y = y;
			this._length = length;
			this._angle = angle;
			
			this._offsetAngle = ( isNaN( offsetAngle ) ? ( Math.PI / 2 ) : offsetAngle ); 
			
			settings = { x:_x, y:_y, length:_length, angle:_angle, offsetAngle:_offsetAngle };
			
		}
		
		
		public function clone():Spidron
		{
			return new Spidron( x, y, length, angle, offsetAngle );
		}
		
		public function reset():void
		{
			this.x = settings.x;
			this.y = settings.y;
			this.length = settings.length;
			this.angle = settings.angle;
			this.offsetAngle = settings.offsetAngle;
			points = new Vector.<Point>();
		}
		
		
		public final function build( iterations:int = 1 ):void
		{
			
			while ( iterations-- ) compute();
		
		}
		
		private final function radians( value:Number):Number  
		{
			return value / 180 * Math.PI;
		}
		
		private final function compute():void 
		{
			
			var a:Point, b:Point, c:Point, d:Point;
			
			var halfLength:Number = length * .5;
			
			
			a = new Point( x + Math.cos( angle ) * halfLength, y + Math.sin( angle ) * halfLength );
			
			b = new Point( x - Math.cos( angle ) * halfLength, y - Math.sin( angle ) * halfLength );
			
			halfLength *= Math.asin( offsetAngle );
			
			c = new Point( 	x + Math.cos( angle + halfPi ) * halfLength, y + Math.sin( angle + halfPi ) * halfLength );
			
			halfLength = GeomUtils.distance( a, c );
			
			var equiAngle:Number = GeomUtils.angle( a, c ) - Math.PI / 3;
			
			d = new Point( 	a.x + Math.cos( equiAngle ) * halfLength,
							a.y + Math.sin( equiAngle ) * halfLength );
			
			
			x = c.x - ( c.x - d.x ) * 0.5; 
			y = c.y - ( c.y - d.y ) * 0.5; 
			length = GeomUtils.distance( c, d );
			angle = GeomUtils.angle( c, d );
			
			points.push( a, b, c, d );
			
			
			
		}
		
		public function get x():Number { return _x; }
		
		public function set x(value:Number):void 
		{
			_x = value;
		}
		
		public function get y():Number { return _y; }
		
		public function set y(value:Number):void 
		{
			_y = value;
		}
		
		public function get length():Number { return _length; }
		
		public function set length(value:Number):void 
		{
			_length = value;
		}
		
		public function get angle():Number { return _angle; }
		
		public function set angle(value:Number):void 
		{
			_angle = value;
		}
		
		public function get offsetAngle():Number { return _offsetAngle; }
		
		public function set offsetAngle(value:Number):void 
		{
			_offsetAngle = value;
		}
		
		public function get points():Vector.<Point> { return _points; }
		
		public function set points(value:Vector.<Point>):void 
		{
			_points = value;
		}
		
	}

}